﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.ServiceModel;
using System.Threading;
using log4net;
using PriceLibrary.PriceService;

namespace PriceLibrary.Utilities
{
    [Obsolete("Don't use anymore.")]
    public class ClientManager : DuplexServiceManager
    {
        public DuplexChannelFactory<IService> ChannelFactory { get; set; }
        private readonly ILog _log;

        #region Contructors

        public ClientManager(string uri)
        {
            ServiceUri = uri;
 //           log4net.Config.XmlConfigurator.Configure(new FileInfo("log4netConfig.xml"));
            _log = LogManager.GetLogger(typeof(ClientManager));

            //_priceCallBack = new PriceCallBack();

            Init(uri);
        }



        #endregion
        [Obsolete("Not used anymore.")]
        public IService CreatePriceServer(PriceCallBack priceCallBack)
        {
            if (priceCallBack == null) throw new ArgumentNullException("PriceCallBack must not be null!");

            PriceCallBack callBack = priceCallBack;
            return callBack.PriceServer;
            //IService server = ChannelFactory.CreateChannel(new InstanceContext(callBack));

            //try
            //{
            //    ((ICommunicationObject)server).Faulted += delegate(object sender, EventArgs e)
            //    {
            //        ICommunicationObject obj = server as ICommunicationObject;
            //        while (obj != null && ((ICommunicationObject)server).State == CommunicationState.Faulted)
            //        {
            //            try
            //            {
            //                if (ChannelFactory != null)
            //                {
            //                    if (ChannelFactory.State != CommunicationState.Faulted)
            //                    {
            //                        server = ChannelFactory.CreateChannel(new InstanceContext(callBack));
            //                        obj = (ICommunicationObject)server;
            //                        Debug.Print("Begin Open");
            //                        obj.Open();
            //                        //Nếu vượt qua câu lệnh trên -> đã mở connection!
            //                        break;
            //                    }
            //                }
            //                else
            //                {
            //                    Init(ServiceUri);
            //                }
            //            }
            //            catch (CommunicationException exception)
            //            {
            //                _log.Error("Server not found!", exception);
            //                Debug.Print("Please wait ....");
            //            }
            //            catch (Exception ex)
            //            {
            //                _log.Error("Unknow exception! Application exit now ...", ex);
            //                break;
            //            }
            //            Thread.Sleep(10 * 1000); //10s
            //        }

            //    };
                //((ICommunicationObject)server).Open();
            //}
            //catch (Exception ex)
            //{
            //    _log.Error("Unknown exception when creates channel!", ex);
            //}
            //finally
            //{
            //    //callBack.PriceServer = server;

            //}
            //return server;
        }

        [Obsolete("Not used anymore.")]
        public PriceCallBack CreateCallBackWithService()
        {
            PriceCallBack callBack = new PriceCallBack(ServiceUri);
            //IService server = ChannelFactory.CreateChannel(new InstanceContext(callBack));
            //try
            //{
            //    ((ICommunicationObject) server).Faulted += delegate
            //                                                   {
            //                                                       //ResolveFaultState(server, callBack);
            //                                                   };
            //    ((ICommunicationObject)server).Open();
            //}
            //catch (Exception ex)
            //{
            //    _log.Error("Unknown exception when creates channel!PriceService", ex);
            //}
            //finally
            //{
            //    callBack.PriceServer = server;
            //}

            return callBack;
        }

        public void ResolveFaultState(IService server, PriceCallBack callBack)
        {
            ICommunicationObject obj = server as ICommunicationObject;
            while (obj != null && (((ICommunicationObject)server).State == CommunicationState.Faulted || ((ICommunicationObject)server).State == CommunicationState.Closed) )
            {
                try
                {
                    if (ChannelFactory != null && ChannelFactory.State != CommunicationState.Faulted)
                    {
                            server = ChannelFactory.CreateChannel(new InstanceContext(callBack));
                            obj = (ICommunicationObject)server;
                            Debug.Print("Begin Open! PriceCallback");
                            obj.Open();
                            //opened connection to service!
                            _log.Info("Begin resubcribe");
                            server.SubscribeNewSymbols((List<string>)callBack.Tickers);
                            server.GetMarketInfos(true);
                            break;
                    }
                    else
                    {
                        Init(ServiceUri);
                    }
                }
                catch (CommunicationException exception)
                {
                    _log.Error("Server not found! PriceCallback", exception);
                    Debug.Print("Please wait ....PriceCallback");
                }
                catch (Exception ex)
                {
                    _log.Error("Unknow exception! PriceCallback", ex);
                    break;
                }
                Thread.Sleep(1 * 1000); //10s
            }
            ((ICommunicationObject) server).Faulted += delegate
                                                           {
                                                               ResolveFaultState(server, callBack);
                                                           };
            //end delegate
        }

        protected void Init(string uri)
        {
            NetTcpBinding netTcpBinding = new NetTcpBinding(SecurityMode.None);
            //netTcpBinding.MaxBufferPoolSize = int.MaxValue;
            netTcpBinding.MaxReceivedMessageSize = netTcpBinding.MaxBufferSize = int.MaxValue;
            netTcpBinding.MaxConnections = 30;

            netTcpBinding.OpenTimeout = TimeSpan.FromMinutes(1.0d);
            netTcpBinding.CloseTimeout = TimeSpan.FromMinutes(1.0d);
            netTcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;

            EndpointAddress endpointAddress = new EndpointAddress(uri);
            ChannelFactory = new DuplexChannelFactory<IService>(typeof(PriceCallBack), netTcpBinding, endpointAddress);
            ChannelFactory.Faulted += FactoryReconnect;

            ChannelFactory.Open();
        }

        private void FactoryReconnect(object sender, EventArgs e)
        {
            while (ChannelFactory == null || ChannelFactory.State == CommunicationState.Faulted)
            {
                Thread.Sleep(10 * 1000); //10s
                Init(ServiceUri);
            }
        }
    }
}
